package com.ihr360.payroll.service.salarytasklet.step.processor;

import com.ihr360.alps.api.ServiceProvider;
import com.ihr360.commons.lang.CollectionUtils;
import com.ihr360.commons.lang.Ihr360NumberUtils;
import com.ihr360.commons.model.type.TaxRole;
import com.ihr360.expr.ExprArray;
import com.ihr360.expr.ExprDouble;
import com.ihr360.expr.parser.ExprToken;
import com.ihr360.job.core.item.ItemProcessor;
import com.ihr360.payroll.config.SalaryTaxEntity;
import com.ihr360.payroll.config.SalaryTaxRuleEntity;
import com.ihr360.payroll.config.SalaryTaxTableEntity;
import com.ihr360.payroll.config.SalaryTaxTypeEntity;
import com.ihr360.payroll.config.TaxDivisionEntity;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.util.Pair;
import org.springframework.util.Assert;

import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
/**
 * @author davidwei
 */
public class TaxTableProcessor implements ItemProcessor<SalaryTaxTableEntity, Pair<String, Map<String, ExprArray>>> {
    final Logger logger = LoggerFactory.getLogger(getClass().getName());
    private static final int TAX_TABLE_FACKDOUBLE_SACALE = 2;
    private static final int TAX_TABLE_RATIO_SACALE = 4;
    private final Date salaryCalcPeriod;

    public TaxTableProcessor(final Date salaryCalcPeriod) {
        this.salaryCalcPeriod = salaryCalcPeriod;
    }

    @Override
    public Pair<String, Map<String, ExprArray>> process(SalaryTaxTableEntity item) throws Exception {
        Assert.notNull(salaryCalcPeriod, "salaryCalcPeriod 账期时间不能为空");
        List<SalaryTaxEntity> taxs = item.getSalaryTaxes();
        TaxDivisionEntity division = item.getDivision();
        TaxRole taxRole = item.getTaxRole();
        SalaryTaxTypeEntity salaryTaxType = item.getType();

        Optional<ExprArray> exprTaxTableOptional = taxs.stream().filter(t -> {
            if (salaryCalcPeriod.after(t.getEffectiveAt())) {
                if (t.getInvalidAt() == null || salaryCalcPeriod.before(t.getInvalidAt())) {
                    return true;
                }
            }
            if (CollectionUtils.isEmpty(t.getRules())) {
                return false;
            }
            return false;
        }).map(t -> {
            //此时返回的税表为排序好的，不需要进行重新排序了
            List<SalaryTaxRuleEntity> rules = t.getRules();
            int rulesSize = rules.size();
            ExprArray exprTaxTable = new ExprArray(rulesSize, 8);
            int row = 0;
            for (SalaryTaxRuleEntity r : rules) {
                long floor = r.getFloor();
                double dFloor = Ihr360NumberUtils.fakeDouble2Double(floor, TAX_TABLE_FACKDOUBLE_SACALE);
                long ceil = 0;
                if (r.getCeil() == null) {
                    //未设置的值为最大值
                    ceil = Long.MAX_VALUE;
                } else {
                    ceil = r.getCeil();
                }

                double dCeil = Ihr360NumberUtils.fakeDouble2Double(ceil, TAX_TABLE_FACKDOUBLE_SACALE);

                long exemption = r.getExamption();
                double dExemption = 0;
                double dExemptionRatio = 0;
                if (r.isFixed()) {
                    dExemption = Ihr360NumberUtils.fakeDouble2Double(exemption, TAX_TABLE_FACKDOUBLE_SACALE);
                } else {
                    dExemptionRatio = Ihr360NumberUtils.fakeDouble2Double(exemption, TAX_TABLE_RATIO_SACALE);
                }


                long taxFloor = r.getTaxFloor();
                double dTaxFloor = Ihr360NumberUtils.fakeDouble2Double(taxFloor, TAX_TABLE_FACKDOUBLE_SACALE);


                long taxCeil = 0;
                if (r.getTaxCeil() == null) {
                    taxCeil = Long.MAX_VALUE;
                }else{
                    taxCeil = r.getTaxCeil();
                }

                double dTaxCeil = Ihr360NumberUtils.fakeDouble2Double(taxCeil, TAX_TABLE_FACKDOUBLE_SACALE);

                int taxRatio = r.getRatio();
                double dTaxRatio = Ihr360NumberUtils.fakeDouble2Double(taxRatio, TAX_TABLE_RATIO_SACALE);

                long reduce = r.getReduce();
                double dReduce = Ihr360NumberUtils.fakeDouble2Double(reduce, TAX_TABLE_FACKDOUBLE_SACALE);

                //为了将所有税种的计算统一话,我们讲有些数据做了荣誉处理，例如 固定免税扣除额和免税扣除比例 真实使用中只会二者取其一。
                //同时将收入和应纳税所得额的上下限制设置进入税表是因为在不同税种的计算时应用的项目不同。
                //收入下限
                exprTaxTable.set(row, 0, new ExprDouble(dFloor));
                //收入上限
                exprTaxTable.set(row, 1, new ExprDouble(dCeil));
                //固定免税扣除额
                exprTaxTable.set(row, 2, new ExprDouble(dExemption));
                //免税扣除比例
                exprTaxTable.set(row, 3, new ExprDouble(dExemptionRatio));
                //应纳税所得额下限
                exprTaxTable.set(row, 4, new ExprDouble(dTaxFloor));
                //应纳税所得额上限
                exprTaxTable.set(row, 5, new ExprDouble(dTaxCeil));
                //税率
                exprTaxTable.set(row, 6, new ExprDouble(dTaxRatio));
                //速算扣除数
                exprTaxTable.set(row, 7, new ExprDouble(dReduce));
                row++;
            }
            return exprTaxTable;

        }).findFirst();
        if (!exprTaxTableOptional.isPresent()) {
            return null;
        }
        StringBuilder builder = new StringBuilder(ServiceProvider.SERVICE_ID.SYS_TAX_TABLE);
        builder.append(ExprToken.NS_FIELD_CONNECTOR.val);
        builder.append(salaryTaxType.getCode());
        Map<String,ExprArray> taxTableMap = new HashMap<>(1);
        taxTableMap.put(builder.toString(), exprTaxTableOptional.get());
        return Pair.of(taxTableCode(division,taxRole), taxTableMap);
    }

    public static String taxTableCode(TaxDivisionEntity taxDivision,TaxRole taxRole){
        StringBuilder builder =new StringBuilder();
        builder.append(taxDivision.getCode());
        builder.append(ServiceProvider.FIELD_CONNECTOR);
        builder.append(taxRole.toString());
        return builder.toString();
    }
    public static String taxTableCode(String taxDivision,String taxRole){
        StringBuilder builder =new StringBuilder();
        builder.append(taxDivision);
        builder.append(ServiceProvider.FIELD_CONNECTOR);
        builder.append(taxRole);
        return builder.toString();
    }
}